package com.zrf.testchatgpt.util;

import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;

import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * MinIO测试
 * 桶中文件已存在，上传时使用不同文件且使用相同文件名，将替换桶中已上传文件
 * 上传时指定文件类型不同，分享链接访问效果也会不同
 * 配置桶规则可实现永久访问buckets > Anonymous，访问方式通过域名+bucketName+文件路径访问
 */
public class MinioUtils {

    private static MinioClient minioClient;

    private final static String MINIO_BUCKET = "bucket1";

    static {
        minioClient = MinioClient.builder()
                .endpoint("http://175.24.165.92:9000")
                .credentials("GoUxgtvUpoohuB6d", "JqSirdliYKWOFMVHZGiUBOveKu7QnvNf")
                .build();
    }

    /**
     * 验证桶是否存在
     *
     * @param bucketName 桶名称
     * @return boolean true-存在；false-不存在
     * @throws Exception
     */
    public static boolean bucketExists(String bucketName) throws Exception {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 获取所有桶列表
     *
     * @return
     * @throws Exception
     */
    public static List<Bucket> listBuckets() throws Exception {
        return minioClient.listBuckets();
    }

    /**
     * 创建桶
     *
     * @param bucketName
     * @throws Exception
     */
    public static void createBucket(String bucketName) throws Exception {
        if (!bucketExists(bucketName)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }


    /**
     * 根据bucketName获取信息
     *
     * @param bucketName bucket名称
     */
    public static Bucket getBucket(String bucketName) throws Exception {
        return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst().orElse(null);
    }


    /**
     * 根据bucketName删除桶信息
     *
     * @param bucketName 桶名称
     * @throws Exception
     */
    public static void removeBucket(String bucketName) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * @param bucketName    桶名称
     * @param objectName    文件名称
     * @param multipartFile multipartFile
     * @throws Exception
     */
    public static ObjectWriteResponse putObject(String bucketName, String objectName, MultipartFile multipartFile) throws Exception {
        return putObject(bucketName, objectName, multipartFile.getInputStream());
    }

    /**
     * 通过文件对象上传文件
     *
     * @param bucketName 桶名称
     * @param objectName 文件名称
     * @param file       文件对象
     * @throws Exception
     */
    public static ObjectWriteResponse putObject(String bucketName, String objectName, File file) throws Exception {
        return putObject(bucketName, objectName, Files.newInputStream(file.toPath()));
    }

    /**
     * 通过文件流上传文件
     *
     * @param bucketName  桶名称
     * @param objectName  文件名称
     * @param inputStream 文件流
     * @throws Exception
     */
    public static ObjectWriteResponse putObject(String bucketName, String objectName, InputStream inputStream) throws Exception {
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName).object(objectName)
                        .stream(inputStream, inputStream.available(), -1)
                        .build());
    }

    /**
     * 根据文件路径上传文件
     *
     * @param bucketName 桶名称
     * @param objectName 文件名称
     * @param filePath   文件路径
     * @throws Exception
     */
    public static ObjectWriteResponse uploadObject(String bucketName, String objectName, String filePath) throws Exception {
        return minioClient.uploadObject(
                UploadObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .filename(filePath)
                        .build());
    }

    public static ObjectWriteResponse putDirObject(String bucketName, String objectName)
            throws Exception {
        return minioClient.putObject(
                PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
                        new ByteArrayInputStream(new byte[]{}), 0, -1).build());
    }

    /**
     * 获取文件流
     *
     * @param bucketName 桶名称
     * @param objectName 文件名称
     * @return
     * @throws Exception
     */
    public static InputStream getObject(String bucketName, String objectName) throws Exception {
        return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }


//    public static List<Item> listObjects(int limit, String bucketName) {
//        List<Item> objects = new ArrayList<>();
//        Iterable<Result<Item>> results = minioClient.listObjects(
//                ListObjectsArgs.builder()
//                        .bucket(bucketName)
//                        .maxKeys(limit)
//                        .includeVersions(true)
//                        .build());
//        try {
//            for (Result<Item> result : results) {
//                objects.add(result.get());
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return objects;
//    }

    /**
     * 获取访问链接，不设置有效期默认时长为7天
     *
     * @param bucketName 桶名称
     * @param objectName 文件名称
     * @param duration   时长
     * @param timeUnit   时间单位
     * @return
     * @throws Exception
     */
    public static String getPreviewUrl(String bucketName, String objectName, int duration, TimeUnit timeUnit) throws Exception {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .method(Method.GET)
                .bucket(bucketName)
                .object(objectName)
                .expiry(duration, timeUnit)
                .build());
    }

    public static void removeObject(String bucketName, String objectName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 批量删除文件
     *
     * @param bucketName bucket
     * @param list       需要删除的文件列表
     */
//    public static void removeObjects(String bucketName, List<String> list) throws Exception {
//        List<DeleteObject> objects = new LinkedList<>();
//        list.forEach(objectName -> objects.add(new DeleteObject(objectName)));
//        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objects).build());
//        for (Result<DeleteError> result : results) {
//            DeleteError deleteError = result.get();
//            System.out.println("error in deleting object:" + deleteError.objectName() + "; " + deleteError.message());
//        }
//    }


    /**
     * 网络文件转储 minio
     *
     * @param bucketName 桶名称
     * @param httpUrl    网络地址
     * @throws Exception
     */
    public static void netToMinio(String bucketName, String httpUrl) {
        int i = httpUrl.lastIndexOf(".");
        String substring = httpUrl.substring(i);
        URL url;
        try {
            url = new URL(httpUrl);
            URLConnection urlConnection = url.openConnection();
            // agent 模拟浏览器
            urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36");
            DataInputStream dataInputStream = new DataInputStream(url.openStream());

            // 临时文件转储
            File tempFile = File.createTempFile(UUID.randomUUID().toString().replace("-", ""), substring);
            FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = dataInputStream.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            fileOutputStream.write(output.toByteArray());
            // 上传minio
            uploadObject(bucketName, tempFile.getName(), tempFile.getAbsolutePath());
            dataInputStream.close();
            fileOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        String nameSuffix = UUID.randomUUID().toString();
        try {
            uploadObject("public",nameSuffix,"C:/Users/asus/Desktop/背景图/a.webp");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


